package com.inforich.app.api.controller.project;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.inforich.app.api.dto.BookingDTO;
import com.inforich.app.api.dto.ProjectDTO;
import com.inforich.app.api.service.IAppProjectService;
import com.inforich.app.api.vo.ProjectVO;
import com.inforich.app.component.LoginUser;
import com.inforich.app.component.LoginUserApp;
import com.inforich.app.component.PreAppRole;
import com.inforich.app.utils.ExportExcelHelper;
import com.inforich.building.domain.BuildingType;
import com.inforich.building.service.IBuildingTypeService;
import com.inforich.carManage.domain.Driver;
import com.inforich.carManage.service.IDriverService;
import com.inforich.common.config.InforichConfig;
import com.inforich.common.constant.Constants;
import com.inforich.common.core.controller.AppBaseController;
import com.inforich.common.core.domain.AjaxResult;
import com.inforich.common.core.domain.TreeSelect;
import com.inforich.common.utils.DateUtils;
import com.inforich.common.utils.file.FileUploadUtils;
import com.inforich.common.utils.uuid.Seq;
import com.inforich.company.domain.TransportCompany;
import com.inforich.company.service.ITransportCompanyService;
import com.inforich.disposal.domain.DisposalLand;
import com.inforich.disposal.service.IDisposalLandService;
import com.inforich.framework.config.ServerConfig;
import com.inforich.projectManage.domain.Project;
import com.inforich.projectManage.domain.ProjectRubbishExpand;
import com.inforich.projectManage.domain.ProjectRubbishRemoval;
import com.inforich.projectManage.domain.ProjectRubbishReport;
import com.inforich.projectManage.domain.StageRubbishDetail;
import com.inforich.projectManage.service.IProjectRubbishDetailService;
import com.inforich.projectManage.service.IProjectRubbishExpandService;
import com.inforich.projectManage.service.IProjectRubbishRemovalService;
import com.inforich.projectManage.service.IProjectRubbishReportService;
import com.inforich.system.service.ISysDictDataService;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @description: 项目管理
 * @author: HJM
 * @date: 2022/10/28
 */
@RestController
@RequestMapping("/h5api/project")
public class AppProjectController extends AppBaseController {

  @Autowired
  private IAppProjectService appProjectService;
  @Autowired
  private ISysDictDataService dictDataService;
  @Autowired
  private IBuildingTypeService buildingTypeService;
  @Autowired
  private IDisposalLandService disposalLandService;
  @Autowired
  private ITransportCompanyService transportCompanyService;
  @Autowired
  private IProjectRubbishExpandService projectRubbishExpandService;
  @Autowired
  private IProjectRubbishRemovalService projectRubbishRemovalService;
  @Autowired
  private IProjectRubbishDetailService projectRubbishDetailService;
  @Autowired
  private IProjectRubbishReportService projectRubbishReportService;
  @Autowired
  private ServerConfig serverConfig;
  @Autowired
  private IDriverService driverService;

  /**
   * 添加项目
   */
  @PostMapping("/add")
  @PreAppRole("project_admin")
  public AjaxResult addProject(@LoginUser LoginUserApp loginUserApp,
      @Validated @RequestBody ProjectDTO projectDTO) {
    return appProjectService.addProject(loginUserApp, projectDTO);
  }

  /**
   * 我的项目
   */
  @GetMapping("/myProject")
  @PreAppRole("project_admin")
  public AjaxResult myProject(@LoginUser LoginUserApp loginUserApp) {
    Project project = appProjectService.getMyProject(loginUserApp);
    if (project == null) {
      return AjaxResult.error("暂无项目信息");
    }
    ProjectVO projectVO = new ProjectVO();
    BeanUtil.copyProperties(project, projectVO);
    return AjaxResult.success(projectVO);
  }

  /**
   * 生成电子档
   */
  @GetMapping("/createDoc")
  @PreAppRole("project_admin")
  public AjaxResult createDoc(@LoginUser LoginUserApp loginUserApp, HttpServletResponse response)
      throws IOException {
    String fileName = "";
    Project project = appProjectService.getMyProject(loginUserApp);
    if ("1".equals(String.valueOf(project.getProjectKindId()))) {
      fileName = Constants.RESOURCE_PREFIX + "/upload/" + createRegisterTable(project, response);
    } else if ("3".equals(String.valueOf(project.getProjectKindId()))) {
      fileName = Constants.RESOURCE_PREFIX + "/upload/" + createRegisterTable(project, response);
    } else if ("2".equals(String.valueOf(project.getProjectKindId()))) {
      fileName = Constants.RESOURCE_PREFIX + "/upload/" + createRecordTable(project, response);
    }
    String url = fileName;

    JSONObject result = new JSONObject();
    result.put("fileName", fileName);
    result.put("url", InforichConfig.getOssUrl() + url);
    return AjaxResult.success(result);
  }

  /**
   * 生成电子档(固废申报)
   */
  @GetMapping("/createDocReport")
  @PreAppRole("project_admin")
  public AjaxResult createDocReport(@LoginUser LoginUserApp loginUserApp,
      HttpServletResponse response) throws IOException {
    Project project = appProjectService.getMyProject(loginUserApp);
    JSONObject result = new JSONObject();
    String path = createApplyTable(project, response);
    if (StrUtil.isBlank(path)) {
      return AjaxResult.error("数据缺失，请先填写完整数据并保存后再下载");
    }
    String fileName = Constants.RESOURCE_PREFIX + "/upload/" + path;

    result.put("url", InforichConfig.getOssUrl() + fileName);
    result.put("fileName", fileName);
    return AjaxResult.success(result);
  }

  /**
   * 生成电子档(预约清理)
   */
  @PostMapping("/createDocBooking")
  @PreAppRole("project_admin")
  public AjaxResult createDocBooking(@LoginUser LoginUserApp loginUserApp,
      @Validated @RequestBody BookingDTO bookingDTO, HttpServletResponse response)
      throws IOException {
    Project project = appProjectService.getMyProject(loginUserApp);
    JSONObject result = new JSONObject();

    Map<String, String> fieldMap = new HashMap<>();
    fieldMap.put("rubbishTypeId", String.valueOf(bookingDTO.getRubbishType()));
    fieldMap.put("projectKindId", String.valueOf(project.getProjectKindId()));
    fieldMap.put("carTypeClassId", String.valueOf(bookingDTO.getCarTypeClassId()));
    fieldMap.put("rubbishStage", String.valueOf(bookingDTO.getRubbishStage()));
    Map<String, String> idField = buildIdField(fieldMap);

    Workbook wb = ExportExcelHelper.createDocBooking(project, bookingDTO, idField);
    String path = uploadExcel(wb, "book");
    IOUtils.closeQuietly(wb);

    if (StrUtil.isBlank(path)) {
      return AjaxResult.error("数据缺失，请先填写完整数据并保存后再下载");
    }
    String fileName = Constants.RESOURCE_PREFIX + "/upload/" + path;
    result.put("url", InforichConfig.getOssUrl() + fileName);
    result.put("fileName", fileName);
    return AjaxResult.success(result);
  }

  /**
   * 垃圾明细
   *
   * @param projectId String
   * @param stage     String
   * @return List<StageRubbishDetail>
   */
  private List<StageRubbishDetail> listStageRubbishDetail(String projectId, String stage) {
    return projectRubbishDetailService.listStageRubbishDetail(projectId, stage);
  }

  /**
   * 构造字典项字段
   *
   * @param fieldMap Map<String,String>
   * @return Map<String, String>
   */
  private Map<String, String> buildIdField(Map<String, String> fieldMap) {
    String buildingTypeId = fieldMap.get("buildingTypeId");
    String structureTypeId = fieldMap.get("structureTypeId");
    String rubbishTypeId = fieldMap.get("rubbishTypeId");
    String projectKindId = fieldMap.get("projectKindId");
    String disposalLandId = fieldMap.get("disposalLandId");
    String transportCompanyId = fieldMap.get("transportCompanyId");
    String carTypeClassId = fieldMap.get("carTypeClassId");
    String rubbishStage = fieldMap.get("rubbishStage");

    Map<String, String> idField = new HashMap<>();
    if (StringUtils.isNotBlank(buildingTypeId)) {
      String buildingType = "";
      List<BuildingType> list = buildingTypeService.list();
      List<TreeSelect> tree = buildingTypeService.selectBuildingTypeTreeList(list);
      Optional<TreeSelect> parentTreeSelect = tree.stream().filter(
          parent -> parent.getChildren().stream()
              .anyMatch(child -> String.valueOf(child.getId()).equals(buildingTypeId))).findFirst();
      Optional<TreeSelect> childTreeSelect = parentTreeSelect.get().getChildren().stream()
          .filter(child -> String.valueOf(child.getId()).equals(buildingTypeId)).findFirst();
      buildingType = parentTreeSelect.get().getLabel() + "/" + childTreeSelect.get().getLabel();

      idField.put("buildingType", buildingType);
    }

    if (StringUtils.isNotBlank(structureTypeId)) {
      String structureType = dictDataService.selectDictLabel("structure_type_id", structureTypeId);
      idField.put("structureType", structureType);
    }

    if (StringUtils.isNotBlank(carTypeClassId)) {
      idField.put("carTypeClassId", dictDataService.selectDictLabel("car_type_id", carTypeClassId));
    }

    if (StringUtils.isNotBlank(rubbishStage)) {
      idField.put("rubbishStage", dictDataService.selectDictLabel("rubbish_stage", rubbishStage));
    }

    if (StringUtils.isNotBlank(rubbishTypeId)) {
      String rubbishType = dictDataService.selectDictLabel("rubbish_type", rubbishTypeId);
      idField.put("rubbishType", rubbishType);
    }

    if (StringUtils.isNotBlank(projectKindId)) {
      String projectKind = dictDataService.selectDictLabel("project_kind_id", projectKindId);
      idField.put("projectKind", projectKind);
    }

    if (StringUtils.isNotBlank(disposalLandId)) {
      DisposalLand disposalLand = disposalLandService.getDisposalLandById(
          Long.valueOf(disposalLandId));
      idField.put("disposalLand", disposalLand.getName());
    }

    if (StringUtils.isNotBlank(transportCompanyId)) {
      TransportCompany transportCompany = transportCompanyService.getTransportCompanyById(
          transportCompanyId);
      idField.put("transportCompany", transportCompany.getName());
    }

    return idField;
  }

  /**
   * 新、改、扩建工程建筑垃圾资源化利用信息登记表
   *
   * @param project  Project
   * @param response HttpServletResponse
   * @throws IOException
   */
  private String createRegisterTable(Project project, HttpServletResponse response)
      throws IOException {
    ProjectRubbishExpand rubbishExpand = projectRubbishExpandService.getProjectRubbishExpandByProjectId(
        project.getId());
    Map<String, List<StageRubbishDetail>> stageRubbishDetailsGroup = new HashMap<>();
    List<StageRubbishDetail> baseList = listStageRubbishDetail(project.getId(), "1");
    List<StageRubbishDetail> mainList = listStageRubbishDetail(project.getId(), "2");
    List<StageRubbishDetail> renovationList = listStageRubbishDetail(project.getId(), "3");
    List<StageRubbishDetail> deliverList = listStageRubbishDetail(project.getId(), "4");

    stageRubbishDetailsGroup.put("base", baseList);
    stageRubbishDetailsGroup.put("main", mainList);
    stageRubbishDetailsGroup.put("renovation", renovationList);
    stageRubbishDetailsGroup.put("deliver", deliverList);

    String buildingTypeId = String.valueOf(rubbishExpand.getBuildingType());
    String structureTypeId = String.valueOf(rubbishExpand.getStructureType());
    String disposalLandId = String.valueOf(rubbishExpand.getDisposalLandId());
    String transportCompanyId = String.valueOf(rubbishExpand.getTransportCompanyId());

    Map<String, String> fieldMap = new HashMap<>();
    fieldMap.put("buildingTypeId", buildingTypeId);
    fieldMap.put("structureTypeId", structureTypeId);
    fieldMap.put("disposalLandId", disposalLandId);
    fieldMap.put("transportCompanyId", transportCompanyId);
    Map<String, String> idField = buildIdField(fieldMap);
    // 车辆信息
    List<Driver> driverList = driverService.list(new LambdaQueryWrapper<Driver>()
        .eq(Driver::getTransportCompanyId, transportCompanyId));
    StringBuilder transportCompanyCarInfo = new StringBuilder(
        rubbishExpand.getTransportCompanyCarInfo());
    transportCompanyCarInfo.append(" 详细信息: ");
    for (Driver driver : driverList) {
      transportCompanyCarInfo.append(" 司机姓名: ")
          .append(driver.getName()).append(" 车牌号: ")
          .append(driver.getCarNumber()).append(";");
    }
    idField.put("transportCompanyCarInfo", transportCompanyCarInfo.toString());

    Workbook wb = ExportExcelHelper.createRegisterTable(project, rubbishExpand, idField,
        stageRubbishDetailsGroup);
    String url = uploadExcel(wb, "xgkdj");
    IOUtils.closeQuietly(wb);
    return url;
  }

  /**
   * 生成excel文件
   *
   * @param wb
   * @param excelName
   * @return
   * @throws IOException
   */
  private String uploadExcel(Workbook wb, String excelName) throws IOException {
    String filePath = InforichConfig.getUploadPath();
    String fileName = com.inforich.common.utils.StringUtils.format("{}/{}_{}.{}", excelName,
        DateUtils.datePath(), Seq.getId(Seq.uploadSeqType), "xlsx");
    String absPath = FileUploadUtils.getAbsoluteFile(filePath, fileName).getAbsolutePath();
    try {
      FileOutputStream output = new FileOutputStream(absPath);
      wb.write(output);
      output.flush();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return fileName;
  }

  /**
   * 拆迁工程建筑垃圾资源化利用信息备案表
   *
   * @param project  Project
   * @param response HttpServletResponse
   * @throws IOException
   */
  private String createRecordTable(Project project, HttpServletResponse response)
      throws IOException {
    ProjectRubbishRemoval rubbishRemoval = projectRubbishRemovalService.getProjectRubbishRemovalByProjectId(
        project.getId());
    Map<String, List<StageRubbishDetail>> stageRubbishDetailsGroup = new HashMap<>();
    List<StageRubbishDetail> dismantleList = listStageRubbishDetail(project.getId(), "5");
    List<StageRubbishDetail> useList = listStageRubbishDetail(project.getId(), "6");

    stageRubbishDetailsGroup.put("dismantle", dismantleList);
    stageRubbishDetailsGroup.put("use", useList);

    String structureTypeId = String.valueOf(rubbishRemoval.getStructureType());
    String disposalLandId = String.valueOf(rubbishRemoval.getDisposalLandId());
    String transportCompanyId = String.valueOf(rubbishRemoval.getTransportCompanyId());

    Map<String, String> fieldMap = new HashMap<>();
    fieldMap.put("structureTypeId", structureTypeId);
    fieldMap.put("disposalLandId", disposalLandId);
    fieldMap.put("transportCompanyId", transportCompanyId);
    Map<String, String> idField = buildIdField(fieldMap);
    // 车辆信息
    List<Driver> driverList = driverService.list(new LambdaQueryWrapper<Driver>()
        .eq(Driver::getTransportCompanyId, transportCompanyId));
    StringBuilder transportCompanyCarInfo = new StringBuilder(
        rubbishRemoval.getTransportCompanyCarInfo());
    transportCompanyCarInfo.append(" 详细信息: ");
    for (Driver driver : driverList) {
      transportCompanyCarInfo.append(" 司机姓名: ")
          .append(driver.getName()).append(" 车牌号: ")
          .append(driver.getCarNumber()).append(";");
    }
    idField.put("transportCompanyCarInfo", transportCompanyCarInfo.toString());
    Workbook wb = ExportExcelHelper.createRecordTable(project, rubbishRemoval, idField,
        stageRubbishDetailsGroup);
    String url = uploadExcel(wb, "cqba");
    IOUtils.closeQuietly(wb);
    return url;
  }

  /**
   * 建筑垃圾运输处置申报表
   *
   * @param project  Project
   * @param response HttpServletResponse
   * @throws IOException
   */
  private String createApplyTable(Project project, HttpServletResponse response)
      throws IOException {
    ProjectRubbishReport rubbishReport = projectRubbishReportService.getProjectRubbishReportByProjectId(
        project.getId());
    if (rubbishReport == null) {
      return "";
    }

    String rubbishTypeId = String.valueOf(rubbishReport.getRubbishType());
    String projectKindId = String.valueOf(project.getProjectKindId());

    Map<String, String> fieldMap = new HashMap<>();
    fieldMap.put("rubbishTypeId", rubbishTypeId);
    fieldMap.put("projectKindId", projectKindId);

    Map<String, String> idField = buildIdField(fieldMap);
    Workbook wb = ExportExcelHelper.createApplyTable(project, rubbishReport, idField);
    String url = uploadExcel(wb, "gfsb");
    IOUtils.closeQuietly(wb);
    return url;
  }
}
